1 /*
2  * The MIT License (MIT)
3  *
4  * Copyright (c) 2014 Devisualization (Richard Andrew Cattermole)
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 module devisualization.window.context.buffer2d;
25 import devisualization.window.window;
26 import devisualization.window.interfaces.context;
27 
28 private enum SRCCOPY = 0x00CC0020;
29 
30 class Buffer2DContext : ContextBuffer2D {
31 	import windows;
32 	import devisualization.image.image;
33 	
34 	private {
35 		PAINTSTRUCT 	ps;
36 		HDC 			hdc;
37 		HDC 			hdcMem;
38 		RECT winsize;
39 		HBITMAP bitmap;
40 
41 		HWND hwnd;
42 		Window window;
43 		
44 		Image buffer_;
45 		ubyte[4][] bufferdata;
46 	}
47 	
48 	this(Window window, WindowConfig config) {
49 		this.window = window;
50 		hwnd = window.hwnd;
51 		
52 		buffer_ = null;
53 	}
54 	
55 	@property {
56 		void activate() {}
57 		void destroy() {}
58 		
59 		void swapBuffers() {
60 			hdc = BeginPaint(hwnd, &ps);
61 			hdcMem = CreateCompatibleDC(hdc);
62 
63 			if (buffer_ !is null) {
64 				// will only reallocate raw data buffer IF the Image buffer size has changed
65 				auto rgba = buffer_.rgba;
66 				bufferdata.length = rgba.length;
67 				
68 				foreach(i, pixel; rgba) {
69 					bufferdata[i][2] = pixel.r_ubyte;
70 					bufferdata[i][1] = pixel.g_ubyte;
71 					bufferdata[i][0] = pixel.b_ubyte;
72 					bufferdata[i][3] = pixel.a_ubyte;
73 				}
74 				
75 				GetClientRect(hwnd, &winsize);
76 				
77 				HBITMAP hBitmap = CreateBitmap(cast(uint)buffer_.width, cast(uint)buffer_.height, 1, 32, bufferdata.ptr);
78 				HGDIOBJ oldBitmap = SelectObject(hdcMem, hBitmap);
79 
80 				GetObjectA(hBitmap, HBITMAP.sizeof, &bitmap);
81 				
82 				// auto stretch the image buffer to client screen size
83 				StretchBlt(hdc, 0, 0, cast(uint)buffer_.width, cast(uint)buffer_.height, hdcMem, 0, 0, winsize.right, winsize.bottom, SRCCOPY);
84 
85 				SelectObject(hdcMem, oldBitmap);
86 				DeleteObject(hBitmap);
87 			}
88 
89 			EndPaint(hwnd, &ps);
90 			DeleteDC(hdcMem);
91 
92 			// perform the actual redraw!
93 			InvalidateRgn(hwnd, null, false);
94 		}
95 		
96 		WindowContextType type() { return WindowContextType.Buffer2D; }
97 		string toolkitVersion() { return null; }
98 		string shadingLanguageVersion() { return null; }
99 		
100 		ref Image buffer() { return buffer_; }
101 		void buffer(Image buffer) { buffer_ = buffer; }
102 	}
103 }